package com.example.server;

import com.example.constant.MessageType;
import com.example.pojo.Header;
import com.example.pojo.NettyMessage;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>  </p>
 *
 * @author Chris
 * @since 2024/3/30 21:58
 */
public class LoginAuthRespHandler extends ChannelInboundHandlerAdapter {
    /**
     * 使用 slf4j 日志框架
     */
    private final static Logger log = LoggerFactory.getLogger(LoginAuthRespHandler.class);

    private final Map<String, Boolean> nodeCheck = new ConcurrentHashMap<>();

    private final String[] whiteList = {"127.0.0.1", "10.0.1.103"};


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        final NettyMessage message = (NettyMessage) msg;
        if (message.getHeader() != null
                && message.getHeader().getType() == MessageType.LOGIN_REQ.value()) {
            final String nodeIndex = ctx.channel().remoteAddress().toString();

            NettyMessage loginResp;
            if (nodeCheck.containsKey(nodeIndex)) {
                loginResp = this.buildResponse((byte) -1);
            } else {
                final InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
                final String ip = address.getAddress().getHostAddress();
                final boolean isOK = Arrays.asList(whiteList).contains(ip);
                loginResp = isOK ? buildResponse((byte) 0) : buildResponse((byte) -1);
                if (isOK) {
                    nodeCheck.put(nodeIndex, true);
                }
            }

            log.info("The login response is : {} body [{}]", loginResp, loginResp.getBody());
            ctx.writeAndFlush(loginResp);
        } else {
            ctx.fireChannelRead(msg);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("error=", cause);

        nodeCheck.remove(ctx.channel().remoteAddress().toString());
        ctx.close();
        ctx.fireExceptionCaught(cause);
    }

    private NettyMessage buildResponse(byte result) {
        final Header header = new Header();
        header.setType(MessageType.LOGIN_RESP.value());

        final NettyMessage message = new NettyMessage();
        message.setHeader(header);
        message.setBody(result);
        return message;
    }

}